package com.yeziji.demo.config.security;

import com.alibaba.druid.pool.DruidDataSource;
import com.yeziji.common.CommonDataSourceConfig;
import com.yeziji.security.common.SecurityDbConfig;
import com.yeziji.security.common.reader.DbInfoReader;
import com.yeziji.security.service.DynamicSecurityDbAuth;
import com.yeziji.utils.DateUtils;
import com.yeziji.utils.expansion.Opt2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 获取论坛的数据源
 *
 * @author hwy
 * @since 2023/11/13 21:50
 **/
@Slf4j
@Service
public class DataSourceAuth implements DynamicSecurityDbAuth {
    @Resource
    private DbInfoReader dbInfoReader;

    @Override
    public DataSource getSecurityDataSource(SecurityDbConfig securityDbConfig) {
        DruidDataSource initDruidDataSource = CommonDataSourceConfig.getInitDruidDataSource();
        initDruidDataSource.setDriverClassName(dbInfoReader.getDriverClassName());
        // 连接信息
        try {
            // 补充数据源连接信息
            this.autoFillSecurityDbLoginInfo(securityDbConfig, dbInfoReader);
            initDruidDataSource.setUrl(securityDbConfig.getUrl());
            initDruidDataSource.setUsername(securityDbConfig.getUsername());
            initDruidDataSource.setPassword(securityDbConfig.getPassword());
        } catch (Exception e) {
            log.error("获取连接信息失败： {}", e.getMessage(), e);
        }
        if (!this.test(securityDbConfig.getUrl(), securityDbConfig.getUsername(), securityDbConfig.getPassword())) {
            log.error("连接信息错误，请重试!!!");
        }
        // 配置初始值、最大活跃数和最小空闲数配置
        initDruidDataSource.setInitialSize(Opt2.nullElse(securityDbConfig.getInitialSize(), initDruidDataSource.getInitialSize()));
        initDruidDataSource.setMaxActive(Opt2.nullElse(securityDbConfig.getMaxActive(), initDruidDataSource.getMaxActive()));
        initDruidDataSource.setMinIdle(Opt2.nullElse(securityDbConfig.getMinIdle(), initDruidDataSource.getMinIdle()));
        // 开启异步初始化策略
        initDruidDataSource.setAsyncInit(Opt2.nullElse(securityDbConfig.getAsyncInit(), true));
        // 设置异常和空闲检测时间
        initDruidDataSource.setTimeBetweenConnectErrorMillis(Opt2.nullElse(securityDbConfig.getTimeBetweenConnectErrorMillis(), initDruidDataSource.getTimeBetweenConnectErrorMillis()));
        initDruidDataSource.setTimeBetweenEvictionRunsMillis(Opt2.nullElse(securityDbConfig.getTimeBetweenEvictionRunsMillis(), initDruidDataSource.getTimeBetweenEvictionRunsMillis()));
        return initDruidDataSource;
    }

    private boolean test(String dbUrl, String username, String password) {
        Connection connection = null;
        try {
            long connectStartTime = System.currentTimeMillis();
            log.info("===== 开始测试连接 =====");
            connection = DriverManager.getConnection(dbUrl, username, password);
            log.info("===== 连接成功, 耗时: {} =====", DateUtils.formatTime(System.currentTimeMillis() - connectStartTime));
        } catch (SQLException e) {
            log.error("===== 连接失败，请确认信息无误：url={}, username={}, password={} =====", dbUrl, username, password, e);
            return false;
        } finally {
            if (connection != null) {
                try {
                    log.info("===== 自动关闭测试连接 =====");
                    connection.close();
                    log.info("===== 自动关闭测试连接成功 =====");
                } catch (SQLException e) {
                    log.error("===== 数据库连接关闭异常 =====");
                }
            }
        }
        return true;
    }
}
